package com.code.service.impl;

import com.code.AZPlan.client.AZPlanStaticIncomeClient;
import com.code.AZPlan.model.po.MoneyTransferRecord;
import com.code.commons.constants.ServerConstants;
import com.code.commons.enums.CacheKeyEnum;
import com.code.commons.enums.ResultCode;
import com.code.commons.exceptions.BusinessException;
import com.code.commons.util.*;
import com.code.commons.web.constants.HeaderConstants;
import com.code.config.profile.ProfileConfig;
import com.code.config.redis.RedisHandler;
import com.code.helper.PasswordHelper;
import com.code.manager.ExchangeHouseManager;
import com.code.manager.FastDFSManager;
import com.code.manager.HttpManager;
import com.code.mapper.ApiMapper;
import com.code.model.bo.AppUpgradeBO;
import com.code.model.bo.FastDFSFile;
import com.code.model.bo.wallet.DepositTran;
import com.code.model.vo.login.LoginCredentialVO;
import com.code.model.vo.user.ModifyPhoneVO;
import com.code.model.vo.user.RegisterUserVO;
import com.code.model.vo.user.TranPwdVO;
import com.code.service.Sms5CService;
import com.code.service.UserService;
import com.code.user.client.LoginCredentialClient;
import com.code.user.client.UserClient;
import com.code.user.model.bo.*;
import com.code.user.model.po.*;
import com.code.user.token.helper.LoginTokenHelper;
import com.code.user.token.service.LoginTokenService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 用户业务聚合服务层
 *
 * @author tangyifei
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    private final static String AREA_NO_PREFIX = "+";

    private final static String AUTH_CODE_ERROR = ":authcodeerror";

    @Value("${dapp.defaultUser}")
    private String defaultUserPhone;

    @Value("${dapp.defaultUserPwd}")
    private String defaultUserPwd;

    @Resource
    private UserClient userClient;

    @Resource
    private LoginCredentialClient loginCredentialClient;

    @Resource
    private RedisHandler redisHandler;

    @Resource
    private Sms5CService sms5CService;

    @Resource
    private LoginTokenService loginTokenService;

    @Resource
    private HttpManager httpManager;

    @Autowired
    ApiMapper apiMapper;

    @Resource
    ExchangeHouseManager exchangeHouseManager;

    @Resource
    private AZPlanStaticIncomeClient azPlanStaticIncomeClient;

    @Resource
    private ProfileConfig profileConfig;

    /**
     * 注册用户
     *
     * @param registerUserVO 用户视图对象
     * @return 影响的行数
     */
    @Override
    public User registerUser(RegisterUserVO registerUserVO) {
        //判断推荐人手机号是否注册，推荐人没有注册不能推荐别人
        String recommenderPhone = registerUserVO.getRecommenderPhone();
        String phone = registerUserVO.getPhone();
        UserRecommender userRecommender = UserRecommender.builder().build();
        //用户类型
        String userType = User.UserTypeEnum.NORMAL.name();
        if (StringUtil.isNotEmpty(recommenderPhone)) {
            if (recommenderPhone.equals(defaultUserPhone)) {
                //指定一个系统推荐人defauldUserPhone
                buildDefaultUser();
            }
            String newPhone = areaNoJoinPhone(phone, registerUserVO.getAreaNo());
            String authCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_REGISTER_AUTH_CODE.formatKey(newPhone)));
            log.info("手机号：【{}】，对应的验证码：【{}】", newPhone, authCode);
            if (StringUtil.isEmpty(authCode) || !authCode.equals(registerUserVO.getAuthCode())) {
                throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
            }
//            Boolean recommenderPhoneIsExist = userClient.judgeUserPhoneIsExist(recommenderPhone);
            LoginUserCredential parentUser = userClient.getUserByPhone(recommenderPhone);
            if (parentUser == null) {
                throw new BusinessException(ResultCode.RECOMMEND_IS_NOT_REGISTER);
            } else if (User.UserTypeEnum.INNER_USER.name().equals(parentUser.getType())) {
                //父级为内部账户，则标记该用户为内部账户
                userType = User.UserTypeEnum.INNER_USER.name();
            }
        } else {
            //没有给出推荐人的，不给注册
            throw new BusinessException(ResultCode.RECOMMEND_USER_IS_NOT_NULL);
        }
        //如果推荐人的手机号与当前注册人的手机号相同，推荐自己就没有意义
        if (recommenderPhone.equals(phone)) {
            throw new BusinessException(ResultCode.CANNOT_RECOMMEND_OWN);
        }
        userRecommender.setRecommenderPhone(recommenderPhone);

        //判断注册用户是否存在
        Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(phone);
        if (userPhoneIsExist) {
            throw new BusinessException(ResultCode.USER_EXISTED);
        }
        //注册用户
        User user = User.builder().phone(phone)
                .gender(User.UserGenderEnum.UNKNOWN.name()).type(userType)
                .status(User.UserStatusEnum.ENABLED.name()).userLevel("V0")
                .inviteCode(registerUserVO.getInviteCode()).areaNo(registerUserVO.getAreaNo()).isAdmin(ServerConstants.COMMON_NO).build();

        //注册用户的凭证信息
        LoginCredential loginCredential = LoginCredential.builder().account(phone).pwd(registerUserVO.getPwd()).build();
        RegisterUser registerUser = new RegisterUser();
        registerUser.setLoginCredential(loginCredential);
        registerUser.setUser(user);
        registerUser.setUserRecommender(userRecommender);
        return userClient.registerUser(registerUser);
    }

    /**
     * @description: 构建系统默认用户
     */
    private void buildDefaultUser() {
        if (StringUtil.isNotEmpty(defaultUserPhone) || StringUtil.isNotEmpty(defaultUserPwd)) {
            LoginUserCredential defaultUser = userClient.getUserByPhone(defaultUserPhone);
            if (defaultUser == null) {
                RegisterUser registerDefaultUser = new RegisterUser();
                registerDefaultUser.setUser(User.builder().phone(defaultUserPhone).gender(User.UserGenderEnum.UNKNOWN.name()).type(User.UserTypeEnum.NORMAL.name())
                        .status(User.UserStatusEnum.ENABLED.name()).userLevel(ServerConstants.ZERO_LEVEL).areaNo("86").isAdmin(ServerConstants.COMMON_NO).inviteCode(null).build());
                registerDefaultUser.setLoginCredential(LoginCredential.builder().account(defaultUserPhone).pwd(defaultUserPwd).build());
                userClient.registerUser(registerDefaultUser);
            }
        } else {
            throw new BusinessException(ResultCode.SPECIFIED_QUESTIONED_USER_NOT_EXIST);
        }
    }

    /**
     * 提交用户认证
     *
     * @param userCertification 用户认证对象
     * @return 影响的行数
     */
    @Override
    public LoginToken addUserCertification(UserCertification userCertification) {
        String userId = userCertification.getUserId();
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        LoginToken loginToken = LoginTokenHelper.getLoginTokenFromRequest();
        if (null != loginToken && null != loginUser && userId.equals(loginUser.getId())) {
            if (null != userCertification.getCertificationType() && userCertification.getCertificationType() == 1) {
                boolean isIdNumber = IDUtil.isIDNumber(userCertification.getCertificationNumber());
                if (!isIdNumber) {
                    throw new BusinessException(ResultCode.ID_NUMBER_IS_ERROR);
                }
            }
            if (StringUtil.isNotEmpty(userCertification.getCertificationNumber())) {
                int certificationCount = userClient.getUserCertificationCountByCertificationNumber(userCertification.getCertificationNumber());
                if (certificationCount >= 3) {
                    throw new BusinessException(ResultCode.CERTIFICATION_IS_AUTH);
                }
            }
            //判断用户是否已经认证
            UserCertification userCertificationDB = userClient.getUserCertificationByUserId(userId);
            if (null != userCertificationDB) {
                if (StringUtil.isNotEmpty(userCertification.getCertificationBackPhoto()) && StringUtil.isNotEmpty(userCertification.getCertificationFrontPhoto()) && userCertificationDB.getBaseAuthState() != 2) {
                    throw new BusinessException(ResultCode.BASE_AUTH_IS_NOT_PASS);
                }
                if (userCertificationDB.getBaseAuthState() == 2 && userCertificationDB.getHighAuthState() == 2) {
                    throw new BusinessException(ResultCode.USER_IS_AUTH);
                }
            }
            loginUser.setBaseAuthState(2);
            if (StringUtil.isNotEmpty(userCertification.getCertificationBackPhoto()) && StringUtil.isNotEmpty(userCertification.getCertificationFrontPhoto())) {
                loginUser.setHighAuthState(1);
                userCertification.setHighAuthState(1);
            } else {
                loginUser.setHighAuthState(0);
                userCertification.setHighAuthState(0);
            }
            if (StringUtil.isNotEmpty(userCertification.getName())) {
                loginUser.setName(userCertification.getName());
            }
            if (null != userCertification.getCertificationType()) {
                loginUser.setCertificationType(userCertification.getCertificationType());
            }
            loginToken.setLoginUser(loginUser);
            //生成新的token
            LoginToken newToken = loginTokenService.add(loginToken);
            //更新缓存中的token
            String newTokenId = newToken.getId();
            LoginTokenHelper.addLoginTokenIdToCookie(newTokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
            //将token放入请求中
            LoginTokenHelper.addLoginTokenToRequest(newToken);
            userCertification.setBaseAuthState(2);
            userClient.addUserCertification(userCertification);
            return newToken;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 获取用户认证详情
     *
     * @param userId 用户主键
     * @return 用户认证详情
     */
    @Override
    public UserCertification getUserCertificationByUserId(String userId) {
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        if (null != loginUser && userId.equals(loginUser.getId())) {
            UserCertification userCertification = userClient.getUserCertificationByUserId(userId);
            if (null == userCertification) {
                return UserCertification.builder().baseAuthState(0).highAuthState(0).build();
            }
            return userCertification;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 注册验证码验证
     *
     * @param phone          手机号
     * @param authCodeClient 验证码
     * @param areaNo         区号
     * @return 影响的行数
     */
    @Override
    public Boolean verifyRegisterAuthCode(String phone, String authCodeClient, String areaNo) {
        phone = areaNoJoinPhone(phone, areaNo);
        String authCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_REGISTER_AUTH_CODE.formatKey(phone)));
        log.info("手机号：【{}】，对应的验证码：【{}】", phone, authCode);
        if (StringUtil.isEmpty(authCode) || !authCode.equals(authCodeClient)) {
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }
        return true;
    }

    /**
     * 发送注册验证码
     *
     * @param phone      手机号
     * @param category   发送验证码的种类，1代表发送注册验证码 2代表发送找回密码时的验证码 3修改手机号发送的验证码 4修改交易密码发送的验证码 5修改登陆密码发送的验证码 6执行提币操作发送的验证码 7站内转账验证码
     * @param areaNo     区号
     * @param phoneIndex 手机号
     * @throws Exception 异常
     */
    @Override
    public void sendAuthCode(String phone, int category, String areaNo, Integer phoneIndex, String recommendPhone) throws Exception {
        // 校验手机号
        if (!ValidatorUtil.isMobile(phone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }

        String language = RequestContextUtil.getRequest().getHeader(HeaderConstants.LANGUAGE);
        if (StringUtil.isEmpty(language)) {
            language = ServerConstants.CN;
        }
        if (category == 1) {
            if (StringUtil.isEmpty(areaNo)) {
                throw new BusinessException(ResultCode.USER_AREA_NO_IS_NOT_NULL);
            }
            if (StringUtil.isEmpty(recommendPhone)) {
                //没有给出推荐人的，不给注册
                throw new BusinessException(ResultCode.RECOMMEND_USER_IS_NOT_NULL);
            } else if (!defaultUserPhone.equals(recommendPhone) && !userClient.judgeUserPhoneIsExist(recommendPhone)) {
                //如果不是系统主账户，则需要判断推荐人是否已存在
                throw new BusinessException(ResultCode.RECOMMEND_IS_NOT_REGISTER);
            } else if (recommendPhone.equals(phone)) {
                //如果推荐人的手机号与当前注册人的手机号相同，推荐自己就没有意义
                throw new BusinessException(ResultCode.CANNOT_RECOMMEND_OWN);
            }
            String newPhone = areaNoJoinPhone(phone, areaNo);
            //随机生成验证码
            String authCode = VerifyCodeUtil.generateVerifyNum(6);
            log.info("手机号：【{}】，验证码：【{}】", newPhone, authCode);
            //判断手机号是否已存在（是否已经被注册）
            Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(phone);
            if (userPhoneIsExist) {
                throw new BusinessException(ResultCode.USER_PHONE_EXISTED);
            }
            //验证码缓存到redis，有效期5分钟
            redisHandler.set(CacheKeyEnum.SMS_REGISTER_AUTH_CODE.formatKey(newPhone), authCode, CacheKeyEnum.SMS_REGISTER_AUTH_CODE.sec());
            //发送短信
            if (ServerConstants.CN.equals(language)) {
                sms5CService.sendSms(newPhone, "谢谢你注册成为AZ挖矿项目用户，验证码： " + authCode);
            }
            if (ServerConstants.ES.equals(language)) {
                sms5CService.sendSms(newPhone, "Thank you for registering as the user of AZ mining project, verification code:" + authCode);
            }
            if (ServerConstants.HK.equals(language)) {
                sms5CService.sendSms(newPhone, "謝謝你注册成為AZ挖礦項目用戶，驗證碼：" + authCode);
            }
            if (ServerConstants.JP.equals(language)) {
                sms5CService.sendSms(newPhone, "AZ掘削プロジェクトのユーザーに登録してくれてありがとうございます，認証コード:" + authCode);
            }
            if (ServerConstants.KR.equals(language)) {
                sms5CService.sendSms(newPhone, "AZ 파광 프로젝트 사용자 등록해 주셔서 감사합니다, 인증번호:" + authCode);
            }
        }
        if (category == 2) {
            //校验用户是否注册了
            Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(phone);
            if (!userPhoneIsExist) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //获取区号
            LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
            if (null == loginUserCredential) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            areaNo = loginUserCredential.getAreaNo();
            String newPhone = areaNoJoinPhone(phone, areaNo);
            //随机生成验证码
            String authCode = VerifyCodeUtil.generateVerifyNum(6);
            log.info("手机号：【{}】，验证码：【{}】", newPhone, authCode);
            //验证码缓存到redis，有效期5分钟
            redisHandler.set(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(newPhone), authCode, CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.sec());
            redisHandler.del(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(newPhone) + AUTH_CODE_ERROR);
            //发送短信
            if (ServerConstants.CN.equals(language)) {
                sms5CService.sendSms(newPhone, "找回密码时的验证码： " + authCode);
            }
            if (ServerConstants.ES.equals(language)) {
                sms5CService.sendSms(newPhone, "Verification code when retrieving the password:" + authCode);
            }
            if (ServerConstants.HK.equals(language)) {
                sms5CService.sendSms(newPhone, "找回密碼時的驗證碼：" + authCode);
            }
            if (ServerConstants.JP.equals(language)) {
                sms5CService.sendSms(newPhone, "パスワードを取り返すときの検証コード：" + authCode);
            }
            if (ServerConstants.KR.equals(language)) {
                sms5CService.sendSms(newPhone, "비밀번호 찾을 때의 인증번호：" + authCode);
            }
        }
        if (category == 3) {
            String newPhone;
            if (phoneIndex != null && phoneIndex == 1) {
                //生成新手机号的验证码
                if (StringUtil.isEmpty(areaNo)) {
                    throw new BusinessException(ResultCode.USER_AREA_NO_IS_NOT_NULL);
                }
                Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(phone);
                if (userPhoneIsExist) {
                    throw new BusinessException(ResultCode.USER_PHONE_EXISTED);
                }
                //获取区号
                newPhone = areaNoJoinPhone(phone, areaNo);
            } else {
                //获取旧手机号对应的区号
                LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
                if (null == loginUserCredential) {
                    throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
                }
                //获取区号
                areaNo = loginUserCredential.getAreaNo();
                newPhone = areaNoJoinPhone(phone, areaNo);
            }
            //随机生成验证码
            String authCode = VerifyCodeUtil.generateVerifyNum(6);
            log.info("手机号：【{}】，验证码：【{}】", newPhone, authCode);
            //验证码缓存到redis，有效期5分钟
            redisHandler.set(CacheKeyEnum.SMS_MODIFY_PHONE_AUTH_CODE.formatKey(newPhone), authCode, CacheKeyEnum.SMS_MODIFY_PHONE_AUTH_CODE.sec());
            //发送短信
            if (ServerConstants.CN.equals(language)) {
                sms5CService.sendSms(newPhone, "修改手机号时的验证码： " + authCode);
            }
            if (ServerConstants.ES.equals(language)) {
                sms5CService.sendSms(newPhone, "Verification code when modifying mobile number:" + authCode);
            }
            if (ServerConstants.HK.equals(language)) {
                sms5CService.sendSms(newPhone, "修改手機號時的驗證碼： " + authCode);
            }
            if (ServerConstants.JP.equals(language)) {
                sms5CService.sendSms(newPhone, "電話番号を変更するときの確認コード： " + authCode);
            }
            if (ServerConstants.KR.equals(language)) {
                sms5CService.sendSms(newPhone, "휴대폰 번호 수정 때의 인증번호： " + authCode);
            }
        }
        if (category == 4) {
            //校验用户是否注册了
            Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(phone);
            if (!userPhoneIsExist) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //获取区号
            LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
            if (null == loginUserCredential) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //获取区号
            areaNo = loginUserCredential.getAreaNo();
            String newPhone = areaNoJoinPhone(phone, areaNo);
            //随机生成验证码
            String authCode = VerifyCodeUtil.generateVerifyNum(6);
            log.info("手机号：【{}】，验证码：【{}】", newPhone, authCode);
            //验证码缓存到redis，有效期5分钟
            redisHandler.set(CacheKeyEnum.SMS_MODIFY_TRAN_PWD_AUTH_CODE.formatKey(newPhone), authCode, CacheKeyEnum.SMS_MODIFY_TRAN_PWD_AUTH_CODE.sec());
            //发送短信
            if (ServerConstants.CN.equals(language)) {
                sms5CService.sendSms(newPhone, "修改交易密码时的验证码： " + authCode);
            }
            if (ServerConstants.ES.equals(language)) {
                sms5CService.sendSms(newPhone, "Verification code ( You are changing transaction password now):" + authCode);
            }
            if (ServerConstants.HK.equals(language)) {
                sms5CService.sendSms(newPhone, "修改交易密碼時的驗證碼：" + authCode);
            }
            if (ServerConstants.JP.equals(language)) {
                sms5CService.sendSms(newPhone, "トランザクションパスワードを変更するときの確認コード:" + authCode);
            }
            if (ServerConstants.KR.equals(language)) {
                sms5CService.sendSms(newPhone, "거래 비밀번호 수정 때의 인증번호:" + authCode);
            }
        }
        if (category == 5) {
            //校验用户是否注册了
            Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(phone);
            if (!userPhoneIsExist) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //获取区号
            LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
            if (null == loginUserCredential) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //获取区号
            areaNo = loginUserCredential.getAreaNo();
            String newPhone = areaNoJoinPhone(phone, areaNo);
            //随机生成验证码
            String authCode = VerifyCodeUtil.generateVerifyNum(6);
            log.info("手机号：【{}】，验证码：【{}】", newPhone, authCode);
            //验证码缓存到redis，有效期5分钟
            redisHandler.set(CacheKeyEnum.SMS_LOGIN_PWD_AUTH_CODE.formatKey(newPhone), authCode, CacheKeyEnum.SMS_LOGIN_PWD_AUTH_CODE.sec());
            //发送短信
            if (ServerConstants.CN.equals(language)) {
                sms5CService.sendSms(newPhone, "修改密码时的验证码： " + authCode);
            }
            if (ServerConstants.ES.equals(language)) {
                sms5CService.sendSms(newPhone, "Verification code when changing password:" + authCode);
            }
            if (ServerConstants.HK.equals(language)) {
                sms5CService.sendSms(newPhone, "修改密碼時的驗證碼：" + authCode);
            }
            if (ServerConstants.JP.equals(language)) {
                sms5CService.sendSms(newPhone, "パスワード変更時の確認コード：" + authCode);
            }
            if (ServerConstants.KR.equals(language)) {
                sms5CService.sendSms(newPhone, "비밀번호 수정 때의 인증번호：" + authCode);
            }
        }
        if (category == 6) {
            //校验用户是否注册了
            Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(phone);
            if (!userPhoneIsExist) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //获取区号
            LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
            if (null == loginUserCredential) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //获取区号
            areaNo = loginUserCredential.getAreaNo();
            String newPhone = areaNoJoinPhone(phone, areaNo);
            //随机生成验证码
            String authCode = VerifyCodeUtil.generateVerifyNum(6);
            log.info("手机号：【{}】，验证码：【{}】", newPhone, authCode);
            //验证码缓存到redis，有效期5分钟
            redisHandler.set(CacheKeyEnum.SMS_WITHDRAW_AUTH_CODE.formatKey(newPhone), authCode, CacheKeyEnum.SMS_WITHDRAW_AUTH_CODE.sec());
            //发送短信
            if (ServerConstants.CN.equals(language)) {
                sms5CService.sendSms(newPhone, "进行提币操作的验证码： " + authCode);
            }
            if (ServerConstants.ES.equals(language)) {
                sms5CService.sendSms(newPhone, "Verification code for withdrawing currency:" + authCode);
            }
            if (ServerConstants.HK.equals(language)) {
                sms5CService.sendSms(newPhone, "進行提幣操作的驗證碼： " + authCode);
            }
            if (ServerConstants.JP.equals(language)) {
                sms5CService.sendSms(newPhone, "出金操作の確認コード： " + authCode);
            }
            if (ServerConstants.KR.equals(language)) {
                sms5CService.sendSms(newPhone, "출금 조작할 때의 인증번호： " + authCode);
            }
        }
        if (category == 7) {
            //获取区号
            LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
            if (null == loginUserCredential) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //获取区号
            areaNo = loginUserCredential.getAreaNo();
            String newPhone = areaNoJoinPhone(phone, areaNo);
            //随机生成验证码
            String authCode = VerifyCodeUtil.generateVerifyNum(6);
            log.info("手机号：【{}】，验证码：【{}】", newPhone, authCode);
            //验证码缓存到redis，有效期5分钟
            redisHandler.set(CacheKeyEnum.SMS_IN_SITE_TRANSFER_AUTH_CODE.formatKey(newPhone), authCode, CacheKeyEnum.SMS_IN_SITE_TRANSFER_AUTH_CODE.sec());
            //发送短信
            if (ServerConstants.CN.equals(language)) {
                sms5CService.sendSms(newPhone, "进行站内转账时的验证码： " + authCode);
            }
            if (ServerConstants.ES.equals(language)) {
                sms5CService.sendSms(newPhone, "Verification code for in station transfer:" + authCode);
            }
            if (ServerConstants.HK.equals(language)) {
                sms5CService.sendSms(newPhone, "進行站內轉帳時的驗證碼： " + authCode);
            }
            if (ServerConstants.JP.equals(language)) {
                sms5CService.sendSms(newPhone, "駅構内振替を行う際の検証コード： " + authCode);
            }
            if (ServerConstants.KR.equals(language)) {
                sms5CService.sendSms(newPhone, "역내 이체 시 검증 코드： " + authCode);
            }
        }

    }

    /**
     * 用户登录
     *
     * @param loginCredentialVO 登录凭证视图对象
     * @return 登录的token
     */
    @Override
    public LoginToken login(LoginCredentialVO loginCredentialVO) {
        if (null == loginCredentialVO) {
            throw new BusinessException(ResultCode.USER_LOGIN_CREDENTIAL_IS_NOT_NULL);
        }
        //登陆账号就是手机号
        String mobilePhone = loginCredentialVO.getAccount();
        // 校验手机号
        if (!ValidatorUtil.isMobile(mobilePhone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        //用户密码
        String loginPwd = loginCredentialVO.getPwd();
        if (StringUtil.isEmpty(loginPwd)) {
            throw new BusinessException(ResultCode.USER_PWD_ERROR);
        }
        //判断用户是否存在
        Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(mobilePhone);
        if (!userPhoneIsExist) {
            throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
        }
        //判断用户的账号是否已经冻结（未启用）
        LoginUserCredential loginUserCredential = userClient.getUserByPhone(mobilePhone);
        String userStatus = loginUserCredential.getStatus();
        if (User.UserStatusEnum.DISABLED.name().equalsIgnoreCase(userStatus)) {
            throw new BusinessException(ResultCode.USER_IS_DISABLED);
        }
        String salt = loginUserCredential.getRandomSalt();
        loginPwd = PasswordHelper.encodeBySalt(loginPwd, salt);
        String pwdForDb = loginUserCredential.getPwd();
        log.info("客户端加过密的密码：【{}】,相关手机号：【{}】对应的数据库的密码：【{}】", loginPwd, mobilePhone, pwdForDb);
        if (!pwdForDb.equals(loginPwd)) {
            throw new BusinessException(ResultCode.USER_PWD_ERROR);
        }
        //TODO 如果保证用户只能在一个终端登录，那么更新缓存的token信息并删除登录拦截器中的从请求中获取token的那段代码
//        String tokenId = userClient.getUserTokenByUserPhone(mobilePhone);
//        if (StringUtil.isNotEmpty(tokenId)) {
//            loginTokenService.deleteById(tokenId);
//            //浏览器中删除token
//            LoginTokenHelper.delLoginTokenIdFromCookie();
//        }
        //生成cookie
        LoginToken loginToken = new LoginToken();
        //token一周后过期
        loginToken.setTtl(CacheKeyEnum.VALUE_LOGIN_TOKENS.sec().longValue());
        String ip = IpUtil.getRealIp(RequestContextUtil.getRequest());
        log.info("获取的登陆ip：【{}】", ip);
        loginToken.setIp(ip);
        String callSource = RequestContextUtil.getRequest().getHeader(HeaderConstants.CALL_SOURCE);
        loginToken.setPlatform(callSource);
        loginToken.setCreateTime(new Date());
        //添加登陆凭证到token中
        LoginCredential loginCredential = LoginCredential.builder().account(loginUserCredential.getAccount()).type(loginUserCredential.getLoginCredentialType())
                .id(loginUserCredential.getLoginCredentialId()).build();
        String tranPwd = loginUserCredential.getTranPwd();
        if (StringUtil.isEmpty(tranPwd)) {
            loginCredential.setTranPwdIsNotSet(1);
        } else {
            loginCredential.setTranPwdIsNotSet(0);
        }
        loginToken.setLoginCredential(loginCredential);
        //添加登陆用户信息到token中
        LoginUser loginUser = com.code.user.model.bo.LoginUser.builder().id(loginUserCredential.getId()).nickname(loginUserCredential.getNickname())
                .type(loginUserCredential.getType()).status(loginUserCredential.getStatus()).gender(loginUserCredential.getGender()).avatar(loginUserCredential.getAvatar())
                .phone(loginUserCredential.getPhone()).userLevel(loginUserCredential.getUserLevel()).userCoinBalanceVersion(loginUserCredential.getUserCoinBalanceVersion())
                .areaNo(loginUserCredential.getAreaNo()).isAdmin(loginUserCredential.getIsAdmin()).build();
        UserCertification userCertification = userClient.getUserCertificationByUserId(loginUserCredential.getId());
        if (null == userCertification) {
            loginUser.setBaseAuthState(0);
            loginUser.setHighAuthState(0);
        } else {
            loginUser.setBaseAuthState(userCertification.getBaseAuthState());
            loginUser.setHighAuthState(userCertification.getHighAuthState());
            loginUser.setCertificationType(userCertification.getCertificationType());
            loginUser.setName(userCertification.getName());
        }
        loginToken.setLoginUser(loginUser);
        //将生成的token放入redis缓存中并保存时间为一周
        LoginToken token = loginTokenService.add(loginToken);
        //绑定登陆tokenId与用户的手机号
        userClient.bindingUserTokenAndUserPhone(mobilePhone, token.getId());
        //将生成的cookie添加到浏览器中并保存时间为一周
        LoginTokenHelper.addLoginTokenIdToCookie(token.getId(), CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
        //将token放入请求中
        LoginTokenHelper.addLoginTokenToRequest(token);
        return token;
    }

    /**
     * 用户登录无需输入密码
     *
     * @param loginCredentialVO 登录凭证视图对象
     * @return 登录的token
     */
    @Override
    public LoginToken doLoginNoPwd(LoginCredentialVO loginCredentialVO) {
        if (null == loginCredentialVO) {
            throw new BusinessException(ResultCode.USER_LOGIN_CREDENTIAL_IS_NOT_NULL);
        }
        //登陆账号就是手机号
        String mobilePhone = loginCredentialVO.getAccount();
        // 校验手机号
        if (!ValidatorUtil.isMobile(mobilePhone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        //判断用户是否存在
        Boolean userPhoneIsExist = userClient.judgeUserPhoneIsExist(mobilePhone);
        if (!userPhoneIsExist) {
            throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
        }
        //判断用户的账号是否已经冻结（未启用）
        LoginUserCredential loginUserCredential = userClient.getUserByPhone(mobilePhone);
        String userStatus = loginUserCredential.getStatus();
        if (User.UserStatusEnum.DISABLED.name().equalsIgnoreCase(userStatus)) {
            throw new BusinessException(ResultCode.USER_IS_DISABLED);
        }
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        UserCertification userCertification = userClient.getUserCertificationByUserId(loginUserCredential.getId());
        if (null == userCertification) {
            loginUser.setBaseAuthState(0);
            loginUser.setHighAuthState(0);
        } else {
            loginUser.setBaseAuthState(userCertification.getBaseAuthState());
            loginUser.setHighAuthState(userCertification.getHighAuthState());
            loginUser.setCertificationType(userCertification.getCertificationType());
            loginUser.setName(userCertification.getName());
        }
        LoginToken loginToken = LoginTokenHelper.getLoginTokenFromRequest();
        loginToken.setLoginUser(loginUser);
        //生成新的token
        LoginToken newToken = loginTokenService.add(loginToken);
        //更新缓存中的token
        String newTokenId = newToken.getId();
        LoginTokenHelper.addLoginTokenIdToCookie(newTokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
        //将token放入请求中
        LoginTokenHelper.addLoginTokenToRequest(newToken);
        return newToken;
    }

    /**
     * 退出登录
     */
    @Override
    public void logout() {
        //从缓存中移出token
        String loginTokenId = LoginTokenHelper.getLoginTokenId();
        loginTokenService.deleteById(loginTokenId);
        //浏览器中删除token
        LoginTokenHelper.delLoginTokenIdFromCookie();
        //从请求中删除token
        LoginTokenHelper.addLoginTokenToRequest(null);
    }

    /**
     * 找回密码
     *
     * @param registerUserVO 用户视图对象
     */
    @Override
    public void findPwd(RegisterUserVO registerUserVO) {
        String phone = registerUserVO.getPhone();
        // 校验手机号
        if (!ValidatorUtil.isMobile(phone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        String areaNo = userClient.getUserByPhone(phone).getAreaNo();
        String newPhone = areaNoJoinPhone(phone, areaNo);
        int authCodeErrorCount = 0;
        if (redisHandler.hasKey(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(newPhone) + AUTH_CODE_ERROR)) {
            Object authCodeErrorTimes = redisHandler.get(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(newPhone) + AUTH_CODE_ERROR);
            if (null != authCodeErrorTimes) {
                authCodeErrorCount = (Integer) authCodeErrorTimes;
            }
        }
        log.info("验证码的错误次数：{}", authCodeErrorCount);
        if (authCodeErrorCount > 2) {
            redisHandler.del(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(newPhone));
            throw new BusinessException(ResultCode.AUTH_CODE_EXPIRED);
        }
        String authCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(newPhone)));
        log.info("手机号：【{}】，对应的验证码：【{}】", phone, authCode);
        if (StringUtil.isEmpty(authCode) || !authCode.equals(registerUserVO.getAuthCode())) {
            //更新错误次数
            redisHandler.incr(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(newPhone) + AUTH_CODE_ERROR);
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }
        //判断用户是否存在
        LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
        if (null == loginUserCredential) {
            throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
        }
        String salt = loginUserCredential.getRandomSalt();
        //设置新密码
        String newPwd = registerUserVO.getPwd();
        newPwd = PasswordHelper.encodeBySalt(newPwd, salt);
        //更新密码
        userClient.resetPwd(loginUserCredential.getId(), newPwd);
    }

    /**
     * 重置密码
     *
     * @param registerUserVO 用户视图对象
     */
    @Override
    public void resetPwd(RegisterUserVO registerUserVO) {
        String authCodeClient = registerUserVO.getAuthCode();
        if (StringUtil.isEmpty(authCodeClient)) {
            throw new BusinessException(ResultCode.USER_AUTH_CODE_IS_NOT_NULL);
        }
        String phone = registerUserVO.getPhone();
        // 校验手机号
        if (!ValidatorUtil.isMobile(phone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        //获取区号
        LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
        if (null == loginUserCredential) {
            throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
        }
        //获取区号
        String areaNo = loginUserCredential.getAreaNo();
        String newPhone = areaNoJoinPhone(phone, areaNo);
        //验证验证码
        String authCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_LOGIN_PWD_AUTH_CODE.formatKey(newPhone)));
        log.info("手机号：【{}】，对应的验证码：【{}】", newPhone, authCode);
        if (StringUtil.isEmpty(authCode) || !authCode.equals(authCodeClient)) {
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }
        //用户的旧密码是否一致
        String oldPwd = registerUserVO.getOldPwd();
        String salt = loginUserCredential.getRandomSalt();
        oldPwd = PasswordHelper.encodeBySalt(oldPwd, salt);
        if (!loginUserCredential.getPwd().equals(oldPwd)) {
            throw new BusinessException(ResultCode.USER_OLD_PWD_ERROR);
        }
        //设置新密码
        String newPwd = registerUserVO.getPwd();
        newPwd = PasswordHelper.encodeBySalt(newPwd, salt);
        //更新密码
        userClient.resetPwd(loginUserCredential.getId(), newPwd);
    }

    /**
     * 找回密码验证码验证
     *
     * @param phone          手机号
     * @param authCodeClient 验证码
     * @return 影响的行数
     */
    @Override
    public Boolean verifyFindPwdAuthCode(String phone, String authCodeClient) {
        //获取区号
        String areaNo = userClient.getUserByPhone(phone).getAreaNo();
        phone = areaNoJoinPhone(phone, areaNo);
        int authCodeErrorCount = 0;
        if (redisHandler.hasKey(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(phone) + AUTH_CODE_ERROR)) {
            Object authCodeErrorTimes = redisHandler.get(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(phone) + AUTH_CODE_ERROR);
            if (null != authCodeErrorTimes) {
                authCodeErrorCount = (Integer) authCodeErrorTimes;
            }
        }
        log.info("验证码的错误次数：{}", authCodeErrorCount);
        if (authCodeErrorCount > 2) {
            redisHandler.del(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(phone));
            throw new BusinessException(ResultCode.AUTH_CODE_EXPIRED);
        }
        String authCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(phone)));
        log.info("手机号：【{}】，对应的验证码：【{}】", phone, authCode);
        if (StringUtil.isEmpty(authCode) || !authCode.equals(authCodeClient)) {
            redisHandler.incr(CacheKeyEnum.SMS_FIND_PWD_AUTH_CODE.formatKey(phone) + AUTH_CODE_ERROR);
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }
        return true;
    }

    /**
     * 升级app
     *
     * @return 升级业务对象
     */
    @Override
    public AppUpgradeBO upgradeApp() {
        String appVersionClient = RequestContextUtil.getRequest().getHeader(HeaderConstants.APP_VERSION);
        String appOS = RequestContextUtil.getRequest().getHeader(HeaderConstants.CALL_SOURCE);
        AppUpgradeBO appUpgrade = apiMapper.getAPPVersionByAPPOs(appOS);
        if (null != appUpgrade) {
            if (new BigDecimal(appVersionClient).compareTo(new BigDecimal(appUpgrade.getAppVersion())) < 0) {
                return appUpgrade;
            }
        }
        return null;
    }

    /**
     * 同步用户的充值记录和余额
     */
    @Override
    public void synRechargeTran() throws Exception {
        log.info("同步充值交易开始");
        long begin = System.currentTimeMillis();
        List<UserCoinBalance> userCoinBalanceList = userClient.getUserWalletList(ServerConstants.XWC);
        if (CollectionUtil.isNotEmpty(userCoinBalanceList)) {
            BigDecimal totalRechargeAmount;
            String userId;
//            String coinType;
            String address;
            for (UserCoinBalance userCoinBalance : userCoinBalanceList) {
                address = userCoinBalance.getCoinAddress();
                if (StringUtil.isNotEmpty(address)) {
                    userId = userCoinBalance.getUserId();
                    List<DepositTran> depositTranList;
                    List<RechargeTranRecord> rechargeTranRecordList;
                    //通过用户主键、币种地址、币种类型获取已经同步的充值总金额
                    totalRechargeAmount = userClient.getTotalRechargeAmount(userId, ServerConstants.XWC, address);
                    if (null == totalRechargeAmount) {
                        totalRechargeAmount = BigDecimal.ZERO;
                    }
                    //获取已确认的充值交易
                    depositTranList = httpManager.getDepositTranList(ServerConstants.XWC, address, 3);
                    BigDecimal balance = BigDecimal.ZERO;
                    int depositTranSize = depositTranList.size();
                    rechargeTranRecordList = Lists.newArrayListWithCapacity(depositTranSize);
                    if (CollectionUtil.isNotEmpty(depositTranList)) {
                        RechargeTranRecord rechargeTranRecord;
                        for (DepositTran depositTran : depositTranList) {
                            balance = BigDecimalUtils.add(balance, String.valueOf(depositTran.getAmount()));
                            rechargeTranRecord = new RechargeTranRecord();
                            rechargeTranRecord.setId(SnowFlakeIdUtil.defaultId());
                            rechargeTranRecord.setUserId(userId);
                            rechargeTranRecord.setCoinType(ServerConstants.XWC);
                            rechargeTranRecord.setCoinAddress(address);
                            rechargeTranRecord.setCoinAmount(depositTran.getAmount());
                            rechargeTranRecord.setTxId(depositTran.getTxid());
                            rechargeTranRecord.setTxTime(depositTran.getTxTime());
                            rechargeTranRecord.setCreateTime(depositTran.getCreatedAt());
                            rechargeTranRecord.setConfirmations(depositTran.getConfirmations());
                            rechargeTranRecord.setRechargeType(2);
                            rechargeTranRecordList.add(rechargeTranRecord);
                        }
                    }
                    //修改用户钱包余额表中的余额并插入某一个地址已经同步的充值记录，这个充值记录用于修改用户的币种余额
                    BigDecimal remainBalance = BigDecimalUtils.subtract(String.valueOf(balance), String.valueOf(totalRechargeAmount));
                    if (balance.compareTo(totalRechargeAmount) > 0) {
                        userCoinBalance.setUserId(userId);
                        userCoinBalance.setCoinBalance(remainBalance);
                        userCoinBalance.setVersion(userCoinBalance.getVersion());
                        userCoinBalance.setUpdateTime(new Date());
                        if (CollectionUtil.isNotEmpty(rechargeTranRecordList)) {
                            userCoinBalance.setRechargeTranRecordList(rechargeTranRecordList);
                        }
                        userClient.addCoinBalance(userCoinBalance);
                    }
                }
            }

        }
        log.info("同步交易结束，所花费的时间：【{}】", System.currentTimeMillis() - begin);
    }

    /**
     * 获取用户详情
     *
     * @param userId 用户主键
     * @return 用户详情数据
     */
    @Override
    public User getUserDetail(String userId) {
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        if (null != loginUser && userId.equals(loginUser.getId())) {
            User user = userClient.getById(userId);
            if (null != user) {
                //获取用户的实名认证状态
                UserCertification userCertification = userClient.getUserCertificationByUserId(userId);
                if (null == userCertification) {
                    user.setBaseAuthState(0);
                    user.setHighAuthState(0);
                } else {
                    user.setBaseAuthState(userCertification.getBaseAuthState());
                    user.setHighAuthState(userCertification.getHighAuthState());
                    user.setCertificationType(userCertification.getCertificationType());
                    user.setName(userCertification.getName());
                }
            }
            return user;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 获取某一个用户钱包列表
     *
     * @param userId 用户主键
     * @return 用户钱包列表
     */
    @Override
    public List<UserCoinBalance> getUserCoinBalanceList(String userId) {
        return userClient.getUserCoinBalanceList(userId);
    }

    /**
     * 根据用户主键获取推荐人的直推用户列表
     *
     * @param userId   用户主键
     * @param page     当前页
     * @param pageSize 每页的大小
     * @return 推荐人的直推用户列表
     */
    @Override
    public Map<String, Object> getRecommendsByUserId(String userId, Integer entryMoneyState, Integer page, Integer pageSize) {
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        if (null != loginUser && userId.equals(loginUser.getId())) {
            return userClient.getDirectRecommends(userId, entryMoneyState, page, pageSize);
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 根据手机号获取推荐人的直推用户列表
     *
     * @param phone    手机号
     * @param page     当前页
     * @param pageSize 每页的大小
     * @return 推荐人的直推用户列表
     */
    @Override
    public Map<String, Object> getRecommendsByPhone(String phone, Integer entryMoneyState, Integer page, Integer pageSize) {
        LoginUserCredential user = userClient.getUserByPhone(phone);
        if (null != user) {
            return userClient.getDirectRecommends(user.getId(), entryMoneyState, page, pageSize);
        } else {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
    }

    /**
     * 获取用户认证列表
     *
     * @param userCertificationBO 用户认证查询对象
     * @return 用户认证列表
     */
    @Override
    public UserCertificationBO getUserCertificationList(UserCertificationBO userCertificationBO) {
        return userClient.getUserCertificationList(userCertificationBO);
    }

    /**
     * 更新用户认证信息
     *
     * @param userCertification 用户认证对象
     * @return 影响的行数
     */
    @Override
    public int updateUserCertification(UserCertification userCertification) {
        return userClient.updateUserCertification(userCertification);
    }

    /**
     * 更新系统维护开关
     *
     * @param systemSettingBO 系统维护业务对象
     * @return 影响的行数
     */
    @Override
    public int updateSystemProtect(SystemSettingBO systemSettingBO) {
        String userId = systemSettingBO.getUserId();
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        if (null != loginUser && loginUser.getId().equals(userId)) {
            //用户密码
            String loginPwd = systemSettingBO.getLoginPwd();
            if (StringUtil.isEmpty(loginPwd)) {
                throw new BusinessException(ResultCode.USER_PWD_ERROR);
            }
            User user = userClient.getById(userId);
            if (null == user) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            String mobilePhone = user.getPhone();
            if (StringUtil.isNotEmpty(mobilePhone)) {
                LoginUserCredential loginUserCredential = userClient.getUserByPhone(mobilePhone);
                if (null != loginUserCredential) {
                    String userStatus = loginUserCredential.getStatus();
                    if (User.UserStatusEnum.DISABLED.name().equalsIgnoreCase(userStatus)) {
                        throw new BusinessException(ResultCode.USER_IS_DISABLED);
                    }
                    String salt = loginUserCredential.getRandomSalt();
                    loginPwd = PasswordHelper.encodeBySalt(loginPwd, salt);
                    String pwdForDb = loginUserCredential.getPwd();
                    log.info("客户端加过密的密码：【{}】,相关手机号：【{}】对应的数据库的密码：【{}】", loginPwd, mobilePhone, pwdForDb);
                    if (!pwdForDb.equals(loginPwd)) {
                        throw new BusinessException(ResultCode.USER_PWD_ERROR);
                    }
                    systemSettingBO.setSystemKey(ServerConstants.SYSTEM_PROTECT);
                    return userClient.updateSystemSetting(systemSettingBO);
                }
            }
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
        return 0;
    }

    /**
     * 通过用户手机号的部分信息模糊查询用户手机
     *
     * @param phone 模糊查询的手机号
     * @return 手机号列表
     */
    @Override
    public PhoneBO getUserPhones(String phone, Integer page, Integer pageSize) {
        return userClient.getUserPhones(phone, page, pageSize);
    }

    /**
     * 获取系统维护开关状态
     *
     * @return 系统维护开关状态
     */
    @Override
    public String getSystemProtect() {
        SystemSettingBO systemSettingBO = userClient.getSystemSettingBySystemKey(ServerConstants.SYSTEM_PROTECT);
        if (null != systemSettingBO) {
            return systemSettingBO.getSystemValue();
        }
        return null;
    }

    /**
     * 禁止或者取消用户的相关的操作
     *
     * @param userOperateAuth 用户操作权限PO及持久层对象
     * @return 影响的行数
     */
    @Override
    public int setUserOperate(UserOperateAuth userOperateAuth) {
        return userClient.setUserOperate(userOperateAuth);
    }

    /**
     * 上传头像
     *
     * @param file 文件
     * @return 文件存放到FASTDfs的路径
     */
    @Override
    public LoginToken uploadAvatar(MultipartFile file) {
        if (file.isEmpty()) {
            throw new BusinessException(ResultCode.USER_SELECT_AVATAR_TO_UPLOAD);
        }
        String path = null;
        try {
            Optional<String> pathOptional = saveFile(file);
            if (pathOptional.isPresent()) {
                path = pathOptional.get();
            }
            log.info("You successfully uploaded：【{}】, file path url：【{}】", file.getOriginalFilename(), path);
            String profile = profileConfig.getActiveProfile();
            log.info("当前的环境：【{}】", profile);
            if (ServerConstants.PROD.equals(profile) && StringUtil.isNotEmpty(path)) {
                //将ip地址替换为域名
                path = path.replace("127.0.0.1", "39.108.113.8");
                log.info("替换为域名的url：【{}】", path);
            }

        } catch (Exception e) {
            log.error("upload file failed", e);
        }
        //修改用户头像
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        //头像上传成功后，更新token中的用户头像信息
        LoginToken loginToken = LoginTokenHelper.getLoginTokenFromRequest();
        if (null != loginToken && null != loginUser) {
            String userId = loginUser.getId();
            User user = User.builder().avatar(path).build();
            user.setUpdateTime(new Date());
            userClient.updateByIdSelective(userId, user);

            loginUser.setAvatar(path);
            loginToken.setLoginUser(loginUser);

            //生成新的token
            LoginToken newToken = loginTokenService.add(loginToken);
            //更新缓存中的token
            String newTokenId = newToken.getId();
            LoginTokenHelper.addLoginTokenIdToCookie(newTokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
            //将token放入请求中
            LoginTokenHelper.addLoginTokenToRequest(newToken);
            return newToken;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 上传图片
     *
     * @param file 文件对象
     * @return 图片存储地址
     */
    @Override
    public String uploadPhoto(MultipartFile file) {
        if (file.isEmpty()) {
            throw new BusinessException(ResultCode.USER_SELECT_AVATAR_TO_UPLOAD);
        }
        String path = null;
        try {
            Optional<String> pathOptional = saveFile(file);
            if (pathOptional.isPresent()) {
                path = pathOptional.get();
            }
            log.info("You successfully uploaded：【{}】, file path url：【{}】", file.getOriginalFilename(), path);
            String profile = profileConfig.getActiveProfile();
            log.info("当前的环境：【{}】", profile);
            if (ServerConstants.PROD.equals(profile) && StringUtil.isNotEmpty(path)) {
                //将ip地址替换为域名
                path = path.replace("127.0.0.1", "39.108.113.8");
                log.info("替换为域名的url：【{}】", path);
            }

        } catch (Exception e) {
            log.error("upload file failed", e);
        }
        return path;
    }

    /**
     * 修改个人信息
     *
     * @param loginUser 登陆用户业务对象
     */
    @Override
    public LoginToken modifyPersonalInfo(com.code.user.model.bo.LoginUser loginUser) {
        //判断用户是否已经存在
        String userId = loginUser.getId();
        if (StringUtil.isEmpty(userId)) {
            throw new BusinessException(ResultCode.USER_ID_IS_NOT_NULL);
        }
        LoginToken loginToken = LoginTokenHelper.getLoginTokenFromRequest();
        LoginUser loginUserForReq = LoginTokenHelper.getLoginUserFromRequest();
        if (null != loginToken && null != loginUserForReq && userId.equals(loginUserForReq.getId())) {
            User userForDB = userClient.getById(userId);
            if (null == userForDB) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //修改昵称、头像、用户等级
            String nickName = loginUser.getNickname();
            User user = User.builder().build();
            if (StringUtil.isNotEmpty(nickName)) {
                user.setNickname(nickName);
                loginUserForReq.setNickname(nickName);
            }
            String avatar = loginUser.getAvatar();
            if (StringUtil.isNotEmpty(avatar)) {
                user.setAvatar(avatar);
                loginUserForReq.setAvatar(avatar);
            }
            String userLevel = loginUser.getUserLevel();
            if (StringUtil.isNotEmpty(userLevel)) {
                user.setUserLevel(userLevel);
                loginUserForReq.setUserLevel(userLevel);
            }
            user.setUpdateTime(new Date());
            userClient.updateByIdSelective(userId, user);
            //更新token里面用户的信息(修改昵称、头像、用户等级)
            loginToken.setLoginUser(loginUserForReq);
            //生成新的token
            LoginToken newToken = loginTokenService.add(loginToken);
            //更新缓存中的token
            String newTokenId = newToken.getId();
            LoginTokenHelper.addLoginTokenIdToCookie(newTokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
            //将token放入请求中
            LoginTokenHelper.addLoginTokenToRequest(newToken);
            return newToken;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 修改手机号
     *
     * @param modifyPhoneVO 修改手机号的视图对象
     */
    @Override
    public LoginToken modifyPhone(ModifyPhoneVO modifyPhoneVO) {
        //验证验证码
        String oldPhone = modifyPhoneVO.getOldPhone();
        // 校验手机号
        if (!ValidatorUtil.isMobile(oldPhone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        String areaNo = userClient.getUserByPhone(oldPhone).getAreaNo();
        oldPhone = areaNoJoinPhone(oldPhone, areaNo);
        String oldPhoneAuthCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_MODIFY_PHONE_AUTH_CODE.formatKey(oldPhone)));
        log.info("旧手机号：【{}】，对应的验证码：【{}】", oldPhone, oldPhoneAuthCode);
        String oldPhoneAuthCodeClient = modifyPhoneVO.getOldPhoneAuthCode();
        if (StringUtil.isEmpty(oldPhoneAuthCode) || !oldPhoneAuthCode.equals(oldPhoneAuthCodeClient)) {
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }
        String newPhone = modifyPhoneVO.getNewPhone();
        // 校验手机号
        if (!ValidatorUtil.isMobile(newPhone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        //验证新手机号是否已存在
        if (userClient.judgeUserPhoneIsExist(newPhone)) {
            throw new BusinessException(ResultCode.USER_PHONE_EXISTED);
        }
        String newPhoneJoin = areaNoJoinPhone(newPhone, modifyPhoneVO.getAreaNo());
        String newPhoneAuthCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_MODIFY_PHONE_AUTH_CODE.formatKey(newPhoneJoin)));
        log.info("新手机号：【{}】，对应的验证码：【{}】", newPhoneJoin, newPhoneAuthCode);
        String newPhoneAuthCodeClient = modifyPhoneVO.getNewPhoneAuthCode();
        if (StringUtil.isEmpty(newPhoneAuthCode) || !newPhoneAuthCode.equals(newPhoneAuthCodeClient)) {
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }

        //判断用户是否已经存在
        String userId = modifyPhoneVO.getId();
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        LoginToken loginToken = LoginTokenHelper.getLoginTokenFromRequest();
        if (null != loginToken && null != loginUser && userId.equals(loginUser.getId())) {
            User userForDB = userClient.getById(userId);
            if (null == userForDB) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            //验证手机号
            String oldPhoneForDB = userForDB.getPhone();
            String oldPhoneJoin = areaNoJoinPhone(oldPhoneForDB, areaNo);
            if (!oldPhone.equals(oldPhoneJoin)) {
                throw new BusinessException(ResultCode.USER_OLD_PHONE_IS_NOT_RIGHT);
            }
            //更新手机号
            LoginUserCredential loginUserCredential = userClient.getUserByPhone(oldPhoneForDB);
            Long loginCredentialId = loginUserCredential.getLoginCredentialId();
            User user = User.builder().phone(newPhone).id(userId).build();
            user.setUpdateTime(new Date());
            userClient.updateByIdSelective(userId, user);
            //修改手机号的时候更新用户凭证的账号，因为用户的登录账号就是手机号
            LoginCredential loginCredentialForDB = LoginCredential.builder().id(loginCredentialId).account(newPhone).build();
            loginCredentialForDB.setUpdateTime(new Date());
            loginCredentialClient.updateByIdSelective(loginCredentialId, loginCredentialForDB);
            //更新token里面用户的手机号
            loginUser.setPhone(newPhone);
            loginToken.setLoginUser(loginUser);
            LoginCredential loginCredential = loginToken.getLoginCredential();
            //更新token里面的登陆凭证账号为新的手机号
            loginCredential.setAccount(newPhone);
            loginToken.setLoginCredential(loginCredential);
            //生成新的token
            LoginToken newToken = loginTokenService.add(loginToken);
            //更新缓存中的token
            String newTokenId = newToken.getId();
            LoginTokenHelper.addLoginTokenIdToCookie(newTokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
            //将token放入请求中
            LoginTokenHelper.addLoginTokenToRequest(newToken);
            return newToken;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 修改交易密码
     *
     * @param tranPwdVO 交易密码视图对象
     */
    @Override
    public LoginToken modifyTranPwd(TranPwdVO tranPwdVO) {
        String oldTranPwd = tranPwdVO.getOldTranPwd();
        if (StringUtil.isEmpty(oldTranPwd)) {
            throw new BusinessException(ResultCode.USER_OLD_TRAN_PWD_IS_NOT_NULL);
        }
        //验证验证码
        String phone = tranPwdVO.getPhone();
        //校验手机号
        if (!ValidatorUtil.isMobile(phone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        String areaNo = userClient.getUserByPhone(phone).getAreaNo();
        String newPhone = areaNoJoinPhone(phone, areaNo);
        String authCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_MODIFY_TRAN_PWD_AUTH_CODE.formatKey(newPhone)));
        log.info("手机号：【{}】，对应的验证码：【{}】", newPhone, authCode);
        String authCodeClient = tranPwdVO.getAuthCode();
        if (StringUtil.isEmpty(authCode) || !authCode.equals(authCodeClient)) {
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }
        //判断用户是否已经存在
        LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
        if (null == loginUserCredential) {
            throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
        }
        String userId = loginUserCredential.getId();
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        LoginToken loginToken = LoginTokenHelper.getLoginTokenFromRequest();
        if (null != loginToken && null != loginUser && userId.equals(loginUser.getId())) {
            //用户的旧交易密码是否一致
            String salt = loginUserCredential.getRandomSalt();
            oldTranPwd = PasswordHelper.encodeBySalt(oldTranPwd, salt);
            if (!loginUserCredential.getTranPwd().equals(oldTranPwd)) {
                throw new BusinessException(ResultCode.USER_OLD_TRAN_PWD_ERROR);
            }
            //设置新交易密码
            String newTranPwd = tranPwdVO.getNewTranPwd();
            newTranPwd = PasswordHelper.encodeBySalt(newTranPwd, salt);
            loginCredentialClient.modifyTranPwd(loginUserCredential.getLoginCredentialId(), newTranPwd);
            //更新token里面用户凭证相关的新的交易密码的设置状态
            LoginCredential loginCredential = loginToken.getLoginCredential();
            loginCredential.setTranPwdIsNotSet(0);
            loginToken.setLoginCredential(loginCredential);
            //生成新的token
            LoginToken newToken = loginTokenService.add(loginToken);
            //更新缓存中的token
            String newTokenId = newToken.getId();
            LoginTokenHelper.addLoginTokenIdToCookie(newTokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
            //将token放入请求中
            LoginTokenHelper.addLoginTokenToRequest(newToken);
            return newToken;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 重置交易密码
     *
     * @param tranPwdVO 交易密码视图对象
     */
    @Override
    public LoginToken resetTranPwd(TranPwdVO tranPwdVO) {
        String loginPwd = tranPwdVO.getPwd();
        if (StringUtil.isEmpty(loginPwd)) {
            throw new BusinessException(ResultCode.USER_OLD_TRAN_PWD_IS_NOT_NULL);
        }
        //验证验证码
        String phone = tranPwdVO.getPhone();
        //校验手机号
        if (!ValidatorUtil.isMobile(phone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        String areaNo = userClient.getUserByPhone(phone).getAreaNo();
        String newPhone = areaNoJoinPhone(phone, areaNo);
        String authCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_MODIFY_TRAN_PWD_AUTH_CODE.formatKey(newPhone)));
        log.info("手机号：【{}】，对应的验证码：【{}】", newPhone, authCode);
        String authCodeClient = tranPwdVO.getAuthCode();
        if (StringUtil.isEmpty(authCode) || !authCode.equals(authCodeClient)) {
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }
        //判断用户是否已经存在
        LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
        if (null == loginUserCredential) {
            throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
        }

        String userId = loginUserCredential.getId();
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        LoginToken loginToken = LoginTokenHelper.getLoginTokenFromRequest();
        if (null != loginToken && null != loginUser && userId.equals(loginUser.getId())) {
            //用户的旧交易密码是否一致
            String salt = loginUserCredential.getRandomSalt();
            String loginPwdEncryption = PasswordHelper.encodeBySalt(loginPwd, salt);
            String pwdForDb = loginUserCredential.getPwd();
            log.info("resetTranPwd.客户端加过密的密码：【{}】,相关手机号：【{}】对应的数据库的密码：【{}】", loginPwdEncryption, phone, pwdForDb);
            if (!pwdForDb.equals(loginPwdEncryption)) {
                throw new BusinessException(ResultCode.USER_PWD_ERROR);
            }
            //设置新交易密码
            String newTranPwd = tranPwdVO.getNewTranPwd();
            newTranPwd = PasswordHelper.encodeBySalt(newTranPwd, salt);
            loginCredentialClient.modifyTranPwd(loginUserCredential.getLoginCredentialId(), newTranPwd);
            //更新token里面用户凭证相关的新的交易密码的设置状态
            LoginCredential loginCredential = loginToken.getLoginCredential();
            loginCredential.setTranPwdIsNotSet(0);
            loginToken.setLoginCredential(loginCredential);
            //生成新的token
            LoginToken newToken = loginTokenService.add(loginToken);
            //更新缓存中的token
            String newTokenId = newToken.getId();
            LoginTokenHelper.addLoginTokenIdToCookie(newTokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
            //将token放入请求中
            LoginTokenHelper.addLoginTokenToRequest(newToken);
            return newToken;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 设置交易密码
     *
     * @param tranPwdVO 交易密码视图对象
     */
    @Override
    public LoginToken setTranPwd(TranPwdVO tranPwdVO) {
        //验证验证码
        String phone = tranPwdVO.getPhone();
        // 校验手机号
        if (!ValidatorUtil.isMobile(phone)) {
            throw new BusinessException(ResultCode.USER_PHONE_FORMAT_ERROR);
        }
        String areaNo = userClient.getUserByPhone(phone).getAreaNo();
        String newPhone = areaNoJoinPhone(phone, areaNo);
        String authCode = String.valueOf(redisHandler.get(CacheKeyEnum.SMS_MODIFY_TRAN_PWD_AUTH_CODE.formatKey(newPhone)));
        log.info("手机号：【{}】，对应的验证码：【{}】", newPhone, authCode);
        String authCodeClient = tranPwdVO.getAuthCode();
        if (StringUtil.isEmpty(authCode) || !authCode.equals(authCodeClient)) {
            throw new BusinessException(ResultCode.AUTH_CODE_ERROR);
        }
        //判断用户是否已经存在
        LoginUserCredential loginUserCredential = userClient.getUserByPhone(phone);
        if (null == loginUserCredential) {
            throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
        }
        String userId = loginUserCredential.getId();
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        LoginToken loginToken = LoginTokenHelper.getLoginTokenFromRequest();
        if (null != loginToken && null != loginUser && userId.equals(loginUser.getId())) {
            String salt = loginUserCredential.getRandomSalt();
            //设置新交易密码
            String newTranPwd = tranPwdVO.getNewTranPwd();
            newTranPwd = PasswordHelper.encodeBySalt(newTranPwd, salt);
            loginCredentialClient.modifyTranPwd(loginUserCredential.getLoginCredentialId(), newTranPwd);
            //更新token里面用户凭证相关的新的交易密码的设置状态
            LoginCredential loginCredential = loginToken.getLoginCredential();
            loginCredential.setTranPwdIsNotSet(0);
            loginToken.setLoginCredential(loginCredential);
            //生成新的token
            LoginToken newToken = loginTokenService.add(loginToken);
            //更新缓存中的token
            String newTokenId = newToken.getId();
            LoginTokenHelper.addLoginTokenIdToCookie(newTokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
            //将token放入请求中
            LoginTokenHelper.addLoginTokenToRequest(newToken);
            return newToken;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    @Override
    public String getCoinAddress(String userId, String coinType) throws Exception {
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        if (null != loginUser && userId.equals(loginUser.getId())) {
            //查看当前用户有没有针对某一个币种类型生成地址(注意：一个用户现在只能对应一个相关币种的相关地址，比如XWC每个用户只能有一个XWC相关的地址)
            String address = userClient.getUserCoinAddressByUserId(userId, coinType);
            if (StringUtil.isNotEmpty(address)) {
                return address;
            }
            address = httpManager.getCoinAddress(coinType);
            //更新用户的余额信息表
            UserCoinBalance userCoinBalance = UserCoinBalance.builder().userId(userId).coinAddress(address)
                    .coinType(coinType).build();
            userCoinBalance.setUpdateTime(new Date());
            //确保用户余额表，一个币种地址对应一个用户主键，这样才能通过用户主键修改余额表
            userClient.updateUserCoinAddress(userCoinBalance);
            return address;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 获取某一个用户的入金通道列表
     *
     * @param userId   用户主键
     * @param coinType 币种类型
     * @return 入金通道列表
     */
    @Override
    public Map<String, Object> getAZPlanChannelList(String userId, String coinType) {
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        if (null != loginUser && userId.equals(loginUser.getId())) {
            Map<String, Object> resultMap = Maps.newHashMapWithExpectedSize(1 << 3);
            List<UserAZPlanChannel> userAZPlanChannelList = userClient.getAZPlanChannelList(userId, coinType);
            resultMap.put("userAZPlanChannelList", userAZPlanChannelList);
            //获取XWC兑换USD的兑换比例
            String xwcExchangeUSDRatio = exchangeHouseManager.getTwentyFourHoursMarket(ServerConstants.XWC_USDT);
            resultMap.put("xwcExchangeUSDRatio", xwcExchangeUSDRatio);
            MoneyTransferRecord moneyTransferRecord = azPlanStaticIncomeClient.getMoneyTransferByUserIdAndCoinType(userId, coinType, null, 1);
            resultMap.put("xwcAZPlanWalletVersion", moneyTransferRecord.getXwcAZPlanWalletVersion());
            resultMap.put("moneyTransferVersion", moneyTransferRecord.getVersion());
            return resultMap;
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 用户充值
     *
     * @param rechargeTranRecord 用户充值实体对象
     * @return 影响的行数
     */
    @Override
    public int recharge(RechargeTranRecord rechargeTranRecord) throws Exception {
        LoginUser loginUser = LoginTokenHelper.getLoginUserFromRequest();
        String userId = null;
        String loginUserId = null;
        if (null != rechargeTranRecord) {
            userId = rechargeTranRecord.getUserId();
            loginUserId = rechargeTranRecord.getLoginUserId();
        }
        if (null != loginUser && loginUser.getId().equals(loginUserId)) {
            if (rechargeTranRecord.getCoinAmount().compareTo(BigDecimal.ZERO) < 0) {
                throw new BusinessException(ResultCode.DEPOSIT_IS_TOO_LOW);
            }
            //用户密码
            String loginPwd = rechargeTranRecord.getLoginPwd();
            if (StringUtil.isEmpty(loginPwd)) {
                throw new BusinessException(ResultCode.USER_PWD_ERROR);
            }
            User user = userClient.getById(loginUserId);
            if (null == user) {
                throw new BusinessException(ResultCode.USER_IS_NOT_EXIST);
            }
            String mobilePhone = user.getPhone();
            if (StringUtil.isNotEmpty(mobilePhone)) {
                LoginUserCredential loginUserCredential = userClient.getUserByPhone(mobilePhone);
                if (null != loginUserCredential) {
                    String userStatus = loginUserCredential.getStatus();
                    if (User.UserStatusEnum.DISABLED.name().equalsIgnoreCase(userStatus)) {
                        throw new BusinessException(ResultCode.USER_IS_DISABLED);
                    }
                    String salt = loginUserCredential.getRandomSalt();
                    loginPwd = PasswordHelper.encodeBySalt(loginPwd, salt);
                    String pwdForDb = loginUserCredential.getPwd();
                    log.info("客户端加过密的密码：【{}】,相关手机号：【{}】对应的数据库的密码：【{}】", loginPwd, mobilePhone, pwdForDb);
                    if (!pwdForDb.equals(loginPwd)) {
                        throw new BusinessException(ResultCode.USER_PWD_ERROR);
                    }
                }
            }
            //系统主账户不支持充提和扣除
            if (loginUser.getPhone().equals(defaultUserPhone)) {
                throw new BusinessException(ResultCode.DEFAULT_USER_FUNCTION_LIMIT);
            }
            //获取用户的钱包地址
            String coinType = rechargeTranRecord.getCoinType();
            UserCoinBalance userCoinBalance = userClient.getUserCoinBalance(userId, coinType, null);
            String coinAddress;
            if (StringUtil.isEmpty(userCoinBalance.getCoinAddress())) {
                coinAddress = httpManager.getCoinAddress(coinType);
                //更新币种地址
//                userCoinBalance.setCoinAddress(coinAddress);
                UserCoinBalance userCoinBalanceDB = UserCoinBalance.builder().coinType(coinType).userId(userId).coinAddress(coinAddress).build();
                userCoinBalanceDB.setUpdateTime(new Date());
                userClient.updateUserCoinAddress(userCoinBalanceDB);
            } else {
                coinAddress = userCoinBalance.getCoinAddress();
            }
            Boolean verifyResult = httpManager.verifyCoinAddress(coinType, coinAddress);
            //校验充值的相关币种地址是否正确
            if (verifyResult) {
//                userCoinBalance.setUpdateTime(new Date());
                rechargeTranRecord.setCoinAddress(coinAddress);
                return userClient.recharge(rechargeTranRecord);
            } else {
                throw new BusinessException(ResultCode.VERIFY_COIN_ADDRESS_FAILURE);
            }
        } else {
            throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
        }
    }

    /**
     * 跳转邀请用户注册页面获取推荐人矿池的当前版本号和USDT钱包的账户版本号
     *
     * @param recommenderPhone 推荐人手机号
     * @return 推荐人矿池的当前版本号和USDT钱包的账户版本号
     */
    @Override
    public UserCoinBalanceBO getUsdtVersion(String recommenderPhone) {
        return userClient.getUsdtVersion(recommenderPhone);
    }

    /**
     * 区号与手机号拼接
     *
     * @param areaNo 区号
     * @param phone  手机号
     */
    public static String areaNoJoinPhone(String phone, String areaNo) {
        if (areaNo.startsWith(AREA_NO_PREFIX)) {
            return areaNo + phone;
        } else {
            return AREA_NO_PREFIX + areaNo + phone;
        }
    }

    /**
     * 保存文件
     * 从MultipartFile中读取文件信息，然后使用FastDFSClient将文件上传到FastDFS集群中。
     *
     * @param multipartFile 多文件上传对象
     * @return 文件路径
     * @throws IOException
     */
    public Optional<String> saveFile(MultipartFile multipartFile) throws IOException {
        String[] fileAbsolutePath = {};
        String fileName = multipartFile.getOriginalFilename();
        String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
        byte[] file_buff = null;
        InputStream inputStream = multipartFile.getInputStream();
        if (null != inputStream) {
            int len1 = inputStream.available();
            file_buff = new byte[len1];
            inputStream.read(file_buff);
        }
        inputStream.close();
        FastDFSFile file = new FastDFSFile(fileName, file_buff, ext);
        try {
            // upload to fastdfs
            fileAbsolutePath = FastDFSManager.upload(file);
        } catch (Exception e) {
            log.error("upload file Exception!", e);
        }
        String path = null;
        if (null == fileAbsolutePath) {
            log.error("upload file failed,please upload again!");
        } else {
            path = FastDFSManager.getTrackerUrl() + fileAbsolutePath[0] + "/" + fileAbsolutePath[1];
            log.info("path：【{}】", path);
        }
        return Optional.ofNullable(path);
    }

}
